package nccloud.sso.util;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.sm.misc.BASE64Decoder;
import org.apache.commons.codec.binary.Base64;

import nc.bs.framework.common.RuntimeEnv;
import nc.bs.logging.Logger;
import nc.vo.pub.BusinessException;
import nccloud.framework.core.exception.ExceptionUtils;
import nccloud.security.impl.SignatureTookKit;
import nccloud.sso.dto.SSOParamDTO;

public class SSOUtils {

	public final static String URI = "/service/genThirdPartyAccessToken";
	
	public final static String URL_PREFIX = "http://";
	
	public final static String COLON = ":";//冒号
	
	public final static String CONTENT_TYPE = "application/x-www-form-urlencoded";
	
	public final static String CONTENT_LENGTH = "10000";
	
	public final static String REQUEST_METHOD = "POST";
	
	public final static String FILE_PATH = "resources/sso.properties";
	
	/**
	 * 请求NCC token
	 * @param param
	 * @return
	 * @throws Exception
	 */
	public static String reqToken(SSOParamDTO param) throws Exception {
		String[] req_token_address = param.getReq_token_address().split(":");
		URL url = createReqTokenUrl(req_token_address[0],Integer.parseInt(req_token_address[1]));
		HttpURLConnection hc = openConnection(url,param);
		OutputStream os = null;
        DataOutputStream dos = null;
        String token = "";
        InputStream is = null;
        try {
        	os = hc.getOutputStream();
        	dos = new DataOutputStream(os);
        	dos.writeBytes(genWriteStr(param));
        	dos.flush();
        	is = hc.getInputStream();
        	int ch;
        	while ((ch = is.read()) != -1) {
        		token += String.valueOf((char) ch);
        	}
        }catch(Exception e) {
        	Logger.error(e.getMessage(), e);
        	ExceptionUtils.wrapException(e.getMessage(), e);
        } finally {
            if (dos != null) {
                try {
                    dos.close();
                } catch (Exception e2) {
                	Logger.error(e2.getMessage(), e2);
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (Exception e2) {
                	Logger.error(e2.getMessage(), e2);
                }
            }
            if (is != null)
                try {
                    is.close();
                } catch (Exception e2) {
            }
        }
        return token;
	}
	
	/**
	 * 创建请求Token的URL对象
	 * @param ip
	 * @param port
	 * @return
	 * @throws MalformedURLException
	 */
	private static URL createReqTokenUrl(String ip,int port) throws MalformedURLException{
		return createReqTokenUrl(ip,port,true);
	}
	
	private static URL createReqTokenUrl(String ip,int port,Boolean isNeedCheck) throws MalformedURLException {
		
		if(isNeedCheck && !isHostConnection(ip,port)) {
			throw new MalformedURLException("该IP[\"+ip+\"]和PORT[\"+port+\"]不可访问，请检查！");
		}
		
		StringBuffer sb = new StringBuffer();
		sb.append(URL_PREFIX);
		sb.append(ip);
		sb.append(COLON);
		sb.append(port);
		sb.append(URI);
		
		return new URL(sb.toString());
	} 
	
	
	/**
	 * 打开URL链接
	 * @param url
	 * @return
	 * @throws IOException
	 */
	private static HttpURLConnection openConnection(URL url,SSOParamDTO dto) throws IOException {
		if(url == null) {
			throw new IOException("创建URL对象失败！");
		}
		URLConnection uc = url.openConnection();
		uc.setDoOutput(true);
		uc.setUseCaches(false);
		uc.setRequestProperty("Content-Type",CONTENT_TYPE);
		uc.setRequestProperty("Content-Length", CONTENT_LENGTH);
		uc.setRequestProperty("userid", dto.getUsercode());
		HttpURLConnection hc = (HttpURLConnection) uc;
		hc.setRequestMethod(REQUEST_METHOD);
		return hc;
	}
	
	
	/**
	 * 检查该IP和PORT 是否可访问
	 * @param ip
	 * @param port
	 * @return
	 */
	private static boolean isHostConnection(String ip, int port) {
		Socket socket = new Socket();
		try {
			socket.connect(new InetSocketAddress(ip, port),3000);
		} catch (SocketTimeoutException s) {
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		} finally {
			try {
				socket.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return true;
	}
	
	
	
	private static String genWriteStr(SSOParamDTO dto) throws Exception{
		String ts = (System.currentTimeMillis() + "").substring(0, 6);
		String keys = dto.getUsercode() + dto.getThirdsys_client_security() + ts;
		String usercode = dto.getUsercode();
		String security = new Base64().encodeToString(SignatureTookKit.digestSign(usercode.getBytes("UTF-8"), keys.getBytes("UTF-8")));
		
		boolean isPass = SignatureTookKit.digestVerify(usercode.getBytes("UTF-8"), keys.getBytes("UTF-8"), new BASE64Decoder().decodeBuffer(security));
		if(!isPass) {
			throw new Exception("security验证失败，请重试或者联系管理员！");
		}
		String param = "type=type_security&dsname="+dto.getDatasource()
						+"&usercode="+dto.getUsercode()
						+"&client_id="+dto.getThirdsys_client_id()
						+"&busicentercode="+dto.getBusicentercode()
						+"&security="+security
//						+"&type="+"approve"
						;
		Logger.error("SSO::SSOVisitServlet.doAction"+param);
		String result = param.replaceAll("\\+","%2B");
		return result;
	}
	
	
	public static SSOParamDTO loadSysParam(SSOParamDTO param) throws FileNotFoundException, IOException {
		Properties properties = getNCHomeProperties();
		param.setDatasource(properties.getProperty("datasource"));
		param.setThirdsys_client_id(properties.getProperty("thirdsys_client_id"));
		param.setThirdsys_client_security(properties.getProperty("thirdsys_client_security"));
		param.setReq_token_address(properties.getProperty("req_token_address"));
		param.setBusicentercode(properties.getProperty("busicentercode"));
		param.setIp(properties.getProperty("ip"));
		param.setPort(Integer.parseInt(properties.getProperty("port")));
		
		param.setOauthServerUrl(properties.getProperty("oauth.serverUrl"));
		param.setOauthEsbServerUrl(properties.getProperty("esb.serverUrl"));
		param.setOauthClientId(properties.getProperty("oauth.client_id"));
		param.setOauthClientSecret(properties.getProperty("oauth.client_secret"));
		
		return param;
	}
	/**
	 * 获得注册在home中的properties文件
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	public static Properties getNCHomeProperties() throws FileNotFoundException, IOException {
		Properties properties = new Properties();
		FileInputStream inputStream = new FileInputStream(getRealPath());  //注意路径
		properties.load(inputStream);
		return properties;
	}
	
	/**
	 * 获得真实路径
	 * @return
	 */
	private static String getRealPath() {
		String homePath = RuntimeEnv.getInstance().getNCHome();
		homePath=homePath.replace("\\", "/");
		if(!homePath.endsWith("/")) {
			homePath += "/";
		}
		return homePath+FILE_PATH;
		
	}
	/**
	 * 请求NCC token
	 * @param param
	 * @return
	 * @throws Exception
	 */
	public static String request(String ur,String param, String method) throws Exception {
		URL url = new URL(ur);
		String result = "";
        BufferedReader in = null;
		
		try {
		
		 URL realUrl = new URL(ur);
         // 打开和URL之间的连接
         URLConnection connection = realUrl.openConnection();
         // 设置通用的请求属性
         connection.setRequestProperty("accept", "*/*");
         connection.setRequestProperty("connection", "Keep-Alive");
         connection.setRequestProperty("user-agent",
                 "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
         // 建立实际的连接
         connection.connect();
         // 获取所有响应头字段
         Map<String, List<String>> map = connection.getHeaderFields();
         // 遍历所有的响应头字段
//         for (String key : map.keySet()) {
//             System.out.println(key + "--->" + map.get(key));
//         }
         // 定义 BufferedReader输入流来读取URL的响应
         in = new BufferedReader(new InputStreamReader(
                 connection.getInputStream()));
         String line;
         while ((line = in.readLine()) != null) {
             result += line;
         }
     } catch (Exception e) {
         System.out.println("发送GET请求出现异常！" + e);
         e.printStackTrace();
     }
     // 使用finally块来关闭输入流
     finally {
         try {
             if (in != null) {
                 in.close();
             }
         } catch (Exception e2) {
             e2.printStackTrace();
         }
     }
		
//		URLConnection uc = url.openConnection();
//		uc.setDoOutput(true);
//		uc.setUseCaches(false);
//		uc.setRequestProperty("Content-Type",CONTENT_TYPE);
//		uc.setRequestProperty("Content-Length", CONTENT_LENGTH);
////		uc.setRequestProperty("userid", dto.getUsercode());
//		HttpURLConnection hc = (HttpURLConnection) uc;
//		hc.setRequestMethod(method);
//		OutputStream os = null;
//        DataOutputStream dos = null;
//        String result = "";
//        InputStream is = null;
//        try {
//        	os = hc.getOutputStream();
//        	dos = new DataOutputStream(os);
//        	dos.writeBytes(param);
//        	dos.flush();
//        	is = hc.getInputStream();
//        	int ch;
//        	while ((ch = is.read()) != -1) {
//        		result += String.valueOf((char) ch);
//        	}
//        	Logger.info("SSO:统一认证返回结果："+result);;
//        }catch(Exception e) {
//        	Logger.error(e.getMessage(), e);
//        	ExceptionUtils.wrapException(e.getMessage(), e);
//        } finally {
//            if (dos != null) {
//                try {
//                    dos.close();
//                } catch (Exception e2) {
//                	Logger.error(e2.getMessage(), e2);
//                }
//            }
//            if (os != null) {
//                try {
//                    os.close();
//                } catch (Exception e2) {
//                	Logger.error(e2.getMessage(), e2);
//                }
//            }
//            if (is != null)
//                try {
//                    is.close();
//                } catch (Exception e2) {
//            }
//        }
        return result;
	}
	/**
	 * 推送数据到统一认证平台
	 * @param url
	 * @param entityName
	 * @return
	 * @throws BusinessException
	 * @throws IOException 
	 */
	public static String sendUamPost(String url,String entityName) throws BusinessException, IOException {
		 String result = "";
	        BufferedReader in = null;
	        try {
//	            String urlNameString = url + "?" + param;
	            URL realUrl = new URL(url);
	            // 打开和URL之间的连接
	            URLConnection connection = realUrl.openConnection();
	            // 设置通用的请求属性
	            connection.setRequestProperty("accept", "*/*");
	            connection.setRequestProperty("connection", "Keep-Alive");
	            connection.setRequestProperty("user-agent",
	                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
	            // 建立实际的连接
	            connection.connect();
	            // 获取所有响应头字段
	            Map<String, List<String>> map = connection.getHeaderFields();
	            // 遍历所有的响应头字段
	            for (String key : map.keySet()) {
	                System.out.println(key + "--->" + map.get(key));
	            }
	            // 定义 BufferedReader输入流来读取URL的响应
	            in = new BufferedReader(new InputStreamReader(
	                    connection.getInputStream()));
	            String line;
	            while ((line = in.readLine()) != null) {
	                result += line;
	            }
	        } catch (Exception e) {
	            System.out.println("发送GET请求出现异常！" + e);
	            e.printStackTrace();
	        }
	        // 使用finally块来关闭输入流
	        finally {
	            try {
	                if (in != null) {
	                    in.close();
	                }
	            } catch (Exception e2) {
	                e2.printStackTrace();
	            }
	        }
	        return result;
	}
}
